package com.github.iogogogo.service.impl;

import com.github.iogogogo.common.base.TaskStatusEnums;
import com.github.iogogogo.common.util.IdHelper;
import com.github.iogogogo.common.util.Java8DateTimeUtils;
import com.github.iogogogo.domain.dto.TaskDTO;
import com.github.iogogogo.entity.SysTaskEntity;
import com.github.iogogogo.repository.SysTaskRepository;
import com.github.iogogogo.service.SysTaskService;
import com.github.iogogogo.task.manager.schedule.ScheduledTaskBean;
import com.github.iogogogo.task.manager.schedule.ScheduledTaskService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * Created by tao.zeng on 2021/3/30.
 */
@Service
public class SysTaskServiceImpl implements SysTaskService {

    @Autowired
    private SysTaskRepository taskRepository;

    @Autowired
    private ScheduledTaskService scheduledTaskService;

    @Override
    public List<SysTaskEntity> findAll() {
        return taskRepository.findAll();
    }

    @Transactional(rollbackFor = {Exception.class, Throwable.class})
    @Override
    public SysTaskEntity saveTask(TaskDTO taskDTO) {

        SysTaskEntity taskEntity = new SysTaskEntity();
        taskEntity.setId(IdHelper.id());
        BeanUtils.copyProperties(taskDTO, taskEntity);
        taskEntity.setStatus(TaskStatusEnums.STOP_SUCCESS.getStatus());
        LocalDateTime nowDateTime = Java8DateTimeUtils.nowDateTime();
        taskEntity.setCreateTime(nowDateTime);
        taskEntity.setUpdateTime(nowDateTime);

        return taskRepository.save(taskEntity);
    }

    @Transactional(rollbackFor = {Exception.class, Throwable.class})
    @Override
    public SysTaskEntity updateTask(TaskDTO taskDTO) {

        Long taskId = taskDTO.getId();
        SysTaskEntity entity = tryTaskEntity(taskId);

        SysTaskEntity taskEntity = new SysTaskEntity();
        BeanUtils.copyProperties(taskDTO, taskEntity);
        taskEntity.setUpdateTime(Java8DateTimeUtils.nowDateTime());


        ScheduledTaskBean taskBean = new ScheduledTaskBean(taskDTO.getBeanName(), taskDTO.getMethodName(), taskDTO.getParam());
        // 停止任务
        scheduledTaskService.removeTask(taskBean);

        // 原始状态如果是启动的，恢复启动，否则不做处理
        if (entity.getStatus() == TaskStatusEnums.START_SUCCESS.getStatus()) {
            scheduledTaskService.addCronTask(taskBean, taskDTO.getCron());
        }

        return taskRepository.save(taskEntity);
    }

    @Override
    public Optional<SysTaskEntity> findById(Long taskId) {
        return taskRepository.findById(taskId);
    }

    @Override
    public SysTaskEntity status(Long taskId, int status) {
        SysTaskEntity entity = tryTaskEntity(taskId);

        entity.setUpdateTime(Java8DateTimeUtils.nowDateTime());

        ScheduledTaskBean taskBean = new ScheduledTaskBean(entity.getBeanName(), entity.getMethodName(), entity.getParam());
        switch (status) {
            case TaskAction.TASK_START:
                scheduledTaskService.addCronTask(taskBean, entity.getCron());
                break;
            case TaskAction.TASK_STOP:
                scheduledTaskService.removeTask(taskBean);
                break;
        }
        return entity;
    }

    @Override
    public void delete(Long taskId) {
        SysTaskEntity entity = tryTaskEntity(taskId);

        ScheduledTaskBean taskBean = new ScheduledTaskBean(entity.getBeanName(), entity.getMethodName(), entity.getParam());
        if (entity.getStatus() == TaskStatusEnums.STOP_SUCCESS.getStatus()) {
            scheduledTaskService.removeTask(taskBean);
        }
        taskRepository.deleteById(taskId);
    }

    @Override
    public SysTaskEntity trigger(Long taskId) {
        SysTaskEntity entity = tryTaskEntity(taskId);
        scheduledTaskService.trigger(entity.getBeanName(), entity.getMethodName(), entity.getParam());
        return entity;
    }

    private SysTaskEntity tryTaskEntity(Long taskId) {
        return findById(taskId).orElseThrow(() -> new NullPointerException(String.format("%d 没有获取到对应任务", taskId)));
    }
}
